package com.zengde.ai_sandbox.service;

import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.seg.common.Term;
import com.hankcs.hanlp.seg.Segment;
import com.hankcs.hanlp.tokenizer.StandardTokenizer;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.io.File;
import java.io.IOException;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;

/**
 * 基于HanLP的语义分块服务
 */
@Service
@Slf4j
public class SemanticChunkService {
    
    @PostConstruct
    public void init() {
        try {
            // 使用StandardTokenizer而不是CRFLexicalAnalyzer，避免模型加载问题
            log.info("正在初始化HanLP分析器...");
            
            // 检查HanLP数据路径
            String rootPath = System.getProperty("hanlp.root");
            if (rootPath != null) {
                File rootDir = new File(rootPath);
                if (!rootDir.exists()) {
                    log.info("HanLP数据目录不存在: {}", rootPath);
                    // 使用默认配置，HanLP会自动下载必要的数据
                } else {
                    log.info("HanLP数据目录已存在: {}", rootPath);
                }
            }
            
            // 进行一次分词测试，确保分词器正常工作
            List<Term> terms = StandardTokenizer.segment("测试分词功能是否正常");
            log.info("HanLP分析器初始化完成，分词测试结果: {}", terms);
        } catch (Exception e) {
            log.error("HanLP分析器初始化失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 根据语义将文本分块
     * 
     * @param text 需要分块的文本
     * @param chunkSize 每块的大致字符数
     * @param overlap 块之间的重叠字符数
     * @return 分块后的文本列表
     */
    public List<String> chunkTextBySemantic(String text, int chunkSize, int overlap) {
        if (text == null || text.isEmpty()) {
            return List.of();
        }
        
        List<String> chunks = new ArrayList<>();
        
        try {
            // 1. 分词获取基本单元
            List<Term> termList = StandardTokenizer.segment(text);
            List<String> semanticUnits = extractSemanticUnits(text, termList);
            
            // 2. 根据指定大小进行分块
            int currentLength = 0;
            StringBuilder currentChunk = new StringBuilder();
            
            for (String unit : semanticUnits) {
                // 如果加上这个单元后长度仍在允许范围内，或者当前块为空（防止单个单元超过块大小的情况）
                if (currentLength + unit.length() <= chunkSize || currentChunk.length() == 0) {
                    currentChunk.append(unit);
                    currentLength += unit.length();
                } else {
                    // 当前块已满，添加到结果中
                    chunks.add(currentChunk.toString());
                    
                    // 创建新块，带有重叠部分
                    if (overlap > 0 && currentChunk.length() > overlap) {
                        String overlapText = currentChunk.substring(Math.max(0, currentChunk.length() - overlap));
                        currentChunk = new StringBuilder(overlapText);
                        currentLength = overlapText.length();
                    } else {
                        currentChunk = new StringBuilder();
                        currentLength = 0;
                    }
                    
                    // 添加当前单元到新块
                    currentChunk.append(unit);
                    currentLength += unit.length();
                }
            }
            
            // 添加最后一个块（如果有内容）
            if (currentChunk.length() > 0) {
                chunks.add(currentChunk.toString());
            }
            
        } catch (Exception e) {
            log.error("语义分块过程中出错: {}", e.getMessage(), e);
        }
        
        return chunks;
    }
    
    /**
     * 提取语义单元，主要针对商品属性类文本
     */
    private List<String> extractSemanticUnits(String text, List<Term> termList) {
        List<String> units = new ArrayList<>();
        
        // 识别商品属性模式：属性名+属性值
        StringBuilder currentUnit = new StringBuilder();
        String currentProperty = null;
        
        for (Term term : termList) {
            String word = term.word;
            String nature = term.nature.toString();
            
            // 检测是否是新的属性名
            if (isPropertyName(nature) && currentUnit.length() > 0) {
                // 保存当前单元并开始新单元
                units.add(currentUnit.toString());
                currentUnit = new StringBuilder();
                currentProperty = word;
                currentUnit.append(word);
            } 
            // 如果是数词、量词或者值类词性，与当前属性合并
            else if (isPropertyValue(nature) || isValueConnector(nature)) {
                currentUnit.append(word);
            }
            // 对于其他情况，判断是否为新属性的开始
            else {
                if (currentUnit.length() > 0) {
                    units.add(currentUnit.toString());
                    currentUnit = new StringBuilder();
                }
                currentUnit.append(word);
            }
        }
        
        // 添加最后一个单元
        if (currentUnit.length() > 0) {
            units.add(currentUnit.toString());
        }
        
        // 进一步合并相似属性
        return mergeRelatedUnits(units);
    }
    
    /**
     * 合并相关的语义单元
     */
    private List<String> mergeRelatedUnits(List<String> units) {
        List<String> mergedUnits = new ArrayList<>();
        StringBuilder currentGroup = new StringBuilder();
        String currentType = null;
        
        for (String unit : units) {
            String unitType = getUnitType(unit);
            
            // 如果类型相同，合并到当前组
            if (unitType.equals(currentType) && currentType != null) {
                currentGroup.append(unit);
            } else {
                // 类型不同，保存当前组并开始新组
                if (currentGroup.length() > 0) {
                    mergedUnits.add(currentGroup.toString());
                }
                currentGroup = new StringBuilder(unit);
                currentType = unitType;
            }
        }
        
        // 添加最后一个组
        if (currentGroup.length() > 0) {
            mergedUnits.add(currentGroup.toString());
        }
        
        return mergedUnits;
    }
    
    /**
     * 获取单元的类型
     */
    private String getUnitType(String unit) {
        // 针对常见商品属性进行匹配
        if (unit.contains("重量") || unit.contains("kg") || unit.contains("g") || unit.contains("斤")) {
            return "重量";
        } else if (unit.contains("配送") || unit.contains("频次")) {
            return "配送";
        } else if (unit.contains("套餐") || unit.contains("份量")) {
            return "套餐";
        } else if (unit.contains("产地") || unit.contains("省份") || unit.contains("城市")) {
            return "产地";
        } else if (unit.contains("包装")) {
            return "包装";
        } else if (unit.contains("规格") || unit.contains("大小") || unit.contains("尺寸")) {
            return "规格";
        } else if (unit.contains("保质期") || unit.contains("日期") || unit.contains("时间")) {
            return "时间";
        } else if (unit.contains("厂") || unit.contains("联系")) {
            return "厂家";
        } else if (unit.contains("品牌") || unit.contains("名称")) {
            return "品牌";
        } else if (unit.contains("食用") || unit.contains("烹饪")) {
            return "食用";
        }
        
        // 默认类型
        return "其他";
    }
    
    /**
     * 判断是否是属性名
     */
    private boolean isPropertyName(String nature) {
        return nature.startsWith("n") || nature.equals("nz");
    }
    
    /**
     * 判断是否是属性值
     */
    private boolean isPropertyValue(String nature) {
        return nature.equals("m") || nature.equals("q") || 
               nature.equals("nz") || nature.equals("v") || 
               nature.equals("a") || nature.equals("t");
    }
    
    /**
     * 判断是否是值连接词
     */
    private boolean isValueConnector(String nature) {
        return nature.equals("w") || nature.equals("c");
    }
} 